package is.progetto2.scheduler.backtrack;

public abstract class Problem<P,C> {

	private int n_max_solution = 0;
	private int n_solution = 0;

	protected abstract P firstChoosingPoint();

	protected abstract P nextChoosingPoint(P p);

	protected abstract P lastChoosingPoint();

	protected abstract C firstChoose(P p);

	protected abstract C nextChoose(C c);

	protected abstract C lastChoose(P p);

	protected abstract boolean assignable(C c, P p);

	protected abstract void assigns(C c, P cp);

	protected abstract void deassigns(C c, P cp);

	protected abstract P previusChoosingPoint(P cp);

	protected abstract C lastChooseAssigned(P cp);
	
	protected abstract void writeSolution();

	public Problem(int n_max_solution) {
		this.n_max_solution = n_max_solution;
	}

	public Problem() {
		this(Integer.MAX_VALUE);
	}
	//TODO da rivedere
	public final void resolve(){
		P cp = firstChoosingPoint();
		C c=firstChoose(cp);
		boolean backtrack=false;
		boolean end=false;
		while (!end) {
			while (!backtrack && n_solution < n_max_solution) {
				if (assignable(c, cp)) {
					assigns(c, cp);
					if (cp.equals(lastChoosingPoint())) {
						n_solution++;
						// writeSolution();deassigns(c, cp);
						if (!cp.equals(lastChoosingPoint())) {
							c = nextChoose(c);
						} else {
							backtrack = true;
						}
					} else {
						cp = nextChoosingPoint(cp);
						c = firstChoose(cp);
					}
				} else if (!c.equals(lastChoose(cp))) {
					c = nextChoose(c);
				} else {
					backtrack = true;
				}
			}// while(!backtrack...)
			
			// backward
			end = cp.equals(firstChoosingPoint())
					|| n_solution == n_max_solution;
			while (backtrack && !end) {
				cp = previusChoosingPoint(cp);
				c = lastChooseAssigned(cp);
				deassigns(c, cp);
				if (!c.equals(lastChoose(cp))) {
					c = nextChoose(c);
					backtrack = false;
				} else if (cp.equals(firstChoosingPoint())) {
					backtrack = true;
				}
			}// backward
		}// while(!end)
	}
}
